# uncompyle6 version 3.2.3
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.8 |Anaconda custom (64-bit)| (default, Feb 21 2019, 18:30:04) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: helpers\licensing\features.py
import logging, dateutil.parser
from dateutil.tz import tzlocal
import datetime, pytz
from uuid import UUID
from server.http_responses.http_errors import Http403, ApiErrors
from helpers.licensing import get_local_license, reset_license_refresh
from helpers.licensing.erp_errors import LicenseException
from helpers.setup_types import *
from helpers.constants.jobs import ScanAppTypes
from helpers.hashing import md5

OVS_STANDARD_PRODUCT_CODES = {
    "OVS001",
    "OVS003",
    "OVS005",
    "OVS010",
    "OVS015",
    "OVS020",
    "OVS025",
    "OVS050",
    "OVS100",
    "OVS250",
    "OVS500",
    "OVS10H",
    "OVS001SPLA",
}
OVS_NRF_LICENSES = {"OVS002NFR"}
OVS_POC_LICENSES = {"OVS003POC", "OVS005POC"}
OVS_PRODUCT_CODES = OVS_STANDARD_PRODUCT_CODES.union(OVS_POC_LICENSES).union(
    OVS_NRF_LICENSES
)
_logger = logging.getLogger("helpers.licensing.features")


def is_ovs_product_code(product_code):
    return product_code in OVS_PRODUCT_CODES


def is_on_premise_v11_product_code(product_code):
    return product_code in frozenset(
        {
            "WVSC10",
            "WVSE",
            "WVSF05Q",
            "WVSC",
            "WVSC1005",
            "WVSF10Q",
            "WVSPOC",
            "WVSC1010",
            "WVSSPL",
        }
    )


def is_poc_license(license_data):
    if license_data.get("product_code") in OVS_POC_LICENSES:
        return True
    elif license_data.get("product_code", "").startswith("AOPPOC"):
        return True
    else:
        return False


def is_in_grace_period(license_data):
    """
    grace period is calculated relative to maintenance expiry
    :param license_data:
    :return: date time with the grace period end or null
    """
    if is_poc_license(license_data):
        return
    if license_data["product_code"] == "OVS_EXPIRED":
        return
    if not license_data.get("maintenance_expired"):
        return
    expires = license_data.get("maintenance_expires")
    if expires is None:
        return
        try:
            if not isinstance(expires, datetime.datetime):
                expires = dateutil.parser.parse(expires)
            if expires.tzinfo is None or expires.tzinfo.utcoffset(expires) is None:
                expires = pytz.utc.localize(expires)
        except ValueError:
            return

        expires = expires + (datetime.timedelta(days=90))
        if datetime.datetime.now(tzlocal()) < expires:
            return expires


def is_on_premise_v12_product_code(product_code):
    if product_code == "TRIAL":
        return True
    elif product_code == "AOPPOC":
        return True
    elif product_code.startswith("AOPSTA"):
        return True
    elif product_code.startswith("AOPPRO"):
        return True
    elif product_code.startswith("AOPENT"):
        return True
    elif product_code.startswith("WVSSPL"):
        return True
    else:
        return False


class Features:
    MULTI_USER = "multi_user"
    CONTINUOUS_SCANS = "continuous_scans"
    COMPLIANCE_REPORTS = "compliance_reports"
    TARGET_GROUPS = "target_groups"
    TARGET_BUSINESS_CRITICALITY = "target_business_criticality"
    BUG_TRACKING_INTEGRATION = "bug_tracking_integration"
    EXPORT_WAF = "export_waf"
    TREND_GRAPHS = "trending_graphs"
    ON_PREMISE_UPDATES = "updates"
    ACUMONITOR = "acumonitor"
    API_KEY = "api_key"
    SCANNING_PROFILES = "scanning_profiles"
    VULN_RETEST = "vuln_retest"
    MULTI_ENGINE = "multi_engine"
    OFFLINE_ACTIVATIONS = "offline_activations"
    ENFORCE_ACUNETIX_HEADERS = "acunetix_headers"
    DELETE_TARGETS = "delete_targets"
    PAUSE_RESUME = "pause_resume"


class BaseLicense:
    @staticmethod
    def get_system_license():
        return BaseLicense.get_license_from_license_data(get_local_license())

    @staticmethod
    def get_license_from_license_data(license_data=None):
        if is_setup_type_on_premise():
            if license_data is None:
                license_data = get_local_license()
            secret = "25128b0a92d51e6bf4ea7a40b91b33be911144f7"
            canonical_form = "%s%s%s%06d%06d%s%s%s%s%s" % (
                secret,
                license_data.get("license_key", ""),
                license_data.get("product_code", ""),
                license_data.get("max_targets", 0),
                license_data.get("max_engines", 0),
                "true" if license_data.get("activated") else "false",
                "true" if license_data.get("expired") else "false",
                license_data.get("bxss_user_id", ""),
                license_data.get("bxss_api_key", ""),
                "true" if license_data.get("offline", False) else "false",
            )
            checksum = md5(canonical_form)
            if license_data.get("max_targets", -1) == 0:
                license_data["max_targets"] = None
            if license_data.get("max_engines", -1) == 0:
                license_data["max_engines"] = None
            if checksum != license_data.get("checksum"):
                result = BaseLicense(dict())
                result.error = "license_data_mismatch"
                _logger.error("license checksum error %s", license_data)
                reset_license_refresh()
                return result
            grace_period_end = is_in_grace_period(license_data)
            if grace_period_end:
                license_data["grace_period_end"] = grace_period_end
            product_code = license_data.get("product_code")
            if product_code is None:
                _logger.warning("no product code for license %s", license_data)
            else:
                if product_code == "TRIAL":
                    return OnPremiseTrial(license_data)
                if product_code == "AOPPOC":
                    return OnPremisePocV12(license_data)
                if product_code.startswith("AOPSTA"):
                    return OnPremiseStandardV12(license_data)
                if product_code.startswith("AOPPRO"):
                    return OnPremiseProV12(license_data)
                if product_code.startswith("AOPENT"):
                    return OnPremiseEnterpriseV12(license_data)
                if product_code.startswith("WVSSPL"):
                    return OnPremiseServiceProviderV12(license_data)
                _logger.warning("product code %s not supported", license_data)
        else:
            if is_setup_type_aws():
                if license_data is None:
                    license_data = dict()
                product_code = license_data.get("product_code", "INVALID")
                grace_period_end = is_in_grace_period(license_data)
                if grace_period_end:
                    license_data["grace_period_end"] = grace_period_end
                if product_code is None:
                    _logger.warning("no product code for license %s", license_data)
                else:
                    if product_code == "OVSTRIAL":
                        return OvsTrial(license_data)
                    if product_code == "OVS_FREE_MODE":
                        return OvsFreeMode(license_data)
                    if product_code == "OVS_EXPIRED":
                        return OvsExpired(license_data)
                    if product_code in OVS_POC_LICENSES:
                        return OvsPoc(license_data)
                    if product_code in OVS_NRF_LICENSES:
                        return OvsNrf(license_data)
                    if product_code in OVS_STANDARD_PRODUCT_CODES:
                        return OvsStandard(license_data)
                    _logger.warning("product code %s not supported", license_data)
                result = BaseLicense(dict())
                result.error = "invalid_product_code"
                return result

    def __init__(self, license_data):
        self.license_data = license_data
        self._features = set()
        self.scan_apps = (ScanAppTypes.WVS,)
        self.max_users = 1
        self.max_engines = 1
        self.max_targets = 0
        self.max_demo_targets = 3
        self.max_network_targets = 0
        self.max_scans_per_engine = 1
        self.error = None

    def is_poc_license(self):
        return is_poc_license(self.license_data)

    @property
    def max_scans_per_license(self):
        return 1

    @property
    def license_key(self):
        if self.license_data:
            return self.license_data.get("license_key", "")
        else:
            return ""

    @property
    def max_child_user_count(self):
        if self.max_users is None:
            return
        else:
            return max(0, self.max_users - 1)

    @property
    def limits(self):
        if is_setup_type_on_premise():
            if self.license_data.get("expired", True):
                if self.license_data.get("grace_period_end") is None:
                    return dict(demo_targets=0, standard_targets=0, engines=0, users=1)
                return dict(
                    demo_targets=self.max_demo_targets,
                    standard_targets=self.max_targets,
                    engines=self.max_engines,
                    users=self.max_users,
                )
            if is_setup_type_aws():
                if self.license_data.get("expired", True):
                    if self.license_data.get("grace_period_end") is None:
                        return dict(
                            demo_targets=0,
                            network_targets=0,
                            standard_targets=0,
                            users=1,
                        )
                    return dict(
                        demo_targets=self.max_demo_targets,
                        network_targets=self.max_network_targets,
                        standard_targets=self.max_targets,
                        users=self.max_users,
                    )

    @property
    def features(self):
        features = self._features
        if self.max_users is None or self.max_users > 1:
            features.add(Features.MULTI_USER)
        if is_setup_type_on_premise():
            if self.max_engines is None or self.max_engines > 1:
                features.add(Features.MULTI_ENGINE)
        if self.license_data.get("offline", False) or self.license_data.get(
            "maintenance_expired", True
        ):
            try:
                features.remove(Features.ON_PREMISE_UPDATES)
            except KeyError:
                pass

            return features

    @property
    def license_info(self):
        license_info = dict(self.license_data)
        license_info["error"] = self.error
        return license_info

    def can_license_log_in(self):
        if not self.license_data.get("activated", False):
            return True
        elif not self.license_data.get("maintenance_expired", True):
            return True
        elif self.license_data.get("grace_period_end") is not None:
            return True
        elif not self.license_data.get("expired", True):
            return True
        else:
            return False

    def is_license_grace_period_expired(self):
        return (
            self.license_data.get("activated", False)
            and self.license_data.get("expired", True)
            and self.license_data.get("grace_period_end") is None
        )

    def require_active_license(self):
        if self.license_data.get("expired", True):
            if self.license_data.get("grace_period_end") is None:
                raise Http403("Feature not allowed", code=ApiErrors.LICENSE_EXPIRED)
        if not self.license_data.get("activated", False):
            raise Http403("Feature not allowed", code=ApiErrors.LICENSE_NOT_ACTIVATED)
        if not self.can_license_log_in():
            raise Http403("Feature not allowed", code=ApiErrors.LICENSE_EXPIRED)

    def is_active_license(self):
        try:
            self.require_active_license()
        except Http403:
            return False

        return True

    def require(self, feature):
        if not self.license_data:
            raise Http403("Void license", code=ApiErrors.FEATURE_NOT_ALLOWED)
        if self.license_data.get("expired", True):
            if self.license_data.get("grace_period_end") is None:
                raise Http403("License expired", code=ApiErrors.FEATURE_NOT_ALLOWED)
        if not self.license_data.get("activated", False):
            raise Http403("License not activated", code=ApiErrors.FEATURE_NOT_ALLOWED)
        if isinstance(feature, (list, tuple)):
            for f in feature:
                if f not in self.features:
                    raise Http403(
                        "Feature not allowed", code=ApiErrors.FEATURE_NOT_ALLOWED
                    )

        else:
            if feature not in self.features:
                raise Http403("Feature not allowed", code=ApiErrors.FEATURE_NOT_ALLOWED)

    def has_feature(self, feature):
        try:
            self.require(feature)
        except Http403:
            return False
        except LicenseException as e:
            _logger.exception("has_feature failed with %s", e)
            return False

        return True

    def can_scan(self, scan_app):
        if self.license_data.get("expired", True):
            if self.license_data.get("grace_period_end") is None:
                return False
            if scan_app not in self.scan_apps:
                return False
            return True


class OnlineLicense(BaseLicense):
    def __init__(self, license_data):
        super().__init__(license_data)

    @property
    def max_scans_per_license(self):
        return 2 * self.max_targets


class OvsTrial(OnlineLicense):
    def __init__(self, license_data):
        super().__init__(license_data)
        self._features = {
            Features.MULTI_USER,
            Features.CONTINUOUS_SCANS,
            Features.TARGET_GROUPS,
            Features.TARGET_BUSINESS_CRITICALITY,
            Features.EXPORT_WAF,
            Features.TREND_GRAPHS,
            Features.COMPLIANCE_REPORTS,
            Features.SCANNING_PROFILES,
        }
        self.max_users = 1
        self.scan_apps = (ScanAppTypes.WVS, ScanAppTypes.OVAS)
        self.max_targets = 3
        self.max_network_targets = 3
        self.max_demo_targets = 3

    @property
    def max_scans_per_license(self):
        return self.max_targets


class OvsExpired(OnlineLicense):
    def can_scan(self, scan_app):
        return False

    @property
    def max_scans_per_license(self):
        return 1

    def can_license_log_in(self):
        return False

    def is_license_grace_period_expired(self):
        return True

    def require_active_license(self):
        raise Http403("Feature not allowed", code=ApiErrors.LICENSE_EXPIRED)


class OvsFreeMode(OnlineLicense):
    def __init__(self, license_data):
        super().__init__(license_data)
        self._features = {
            Features.TARGET_BUSINESS_CRITICALITY,
            Features.EXPORT_WAF,
            Features.TREND_GRAPHS,
            Features.COMPLIANCE_REPORTS,
        }
        self.scan_apps = (ScanAppTypes.WVS, ScanAppTypes.OVAS)
        self.max_users = 1
        self.max_targets = 3
        self.max_network_targets = 3

    def can_scan(self, scan_app):
        return scan_app == ScanAppTypes.OVAS


class OvsStandard(OnlineLicense):
    def __init__(self, license_data):
        super().__init__(license_data)
        self._features = {
            Features.CONTINUOUS_SCANS,
            Features.TARGET_GROUPS,
            Features.TARGET_BUSINESS_CRITICALITY,
            Features.BUG_TRACKING_INTEGRATION,
            Features.EXPORT_WAF,
            Features.TREND_GRAPHS,
            Features.COMPLIANCE_REPORTS,
            Features.ACUMONITOR,
            Features.API_KEY,
            Features.SCANNING_PROFILES,
            Features.VULN_RETEST,
            Features.PAUSE_RESUME,
        }
        if license_data["product_code"] == "OVS001SPLA":
            self.max_targets = 1
            self.max_network_targets = 3
        else:
            if license_data["product_code"] == "OVS001":
                self.max_targets = 1
                self.max_network_targets = 3
            else:
                self.max_targets = self.license_data["licenses"]
                self.max_network_targets = self.max_targets
            self.max_users = None


class OvsPoc(OnlineLicense):
    def __init__(self, license_data):
        super().__init__(license_data)
        self._features = {
            Features.MULTI_USER,
            Features.CONTINUOUS_SCANS,
            Features.TARGET_GROUPS,
            Features.TARGET_BUSINESS_CRITICALITY,
            Features.BUG_TRACKING_INTEGRATION,
            Features.EXPORT_WAF,
            Features.TREND_GRAPHS,
            Features.COMPLIANCE_REPORTS,
            Features.ACUMONITOR,
            Features.API_KEY,
            Features.SCANNING_PROFILES,
            Features.VULN_RETEST,
            Features.PAUSE_RESUME,
        }
        self.scan_apps = (ScanAppTypes.WVS, ScanAppTypes.OVAS)
        if license_data["product_code"] == "OVS003POC":
            self.max_targets = 3
        else:
            self.max_targets = 5
        self.max_users = int(self.max_targets / 2) + 1
        self.max_network_targets = self.max_targets


class OvsNrf(OnlineLicense):
    def __init__(self, license_data):
        super().__init__(license_data)
        self._features = {
            Features.CONTINUOUS_SCANS,
            Features.TARGET_GROUPS,
            Features.TARGET_BUSINESS_CRITICALITY,
            Features.BUG_TRACKING_INTEGRATION,
            Features.EXPORT_WAF,
            Features.TREND_GRAPHS,
            Features.COMPLIANCE_REPORTS,
            Features.ACUMONITOR,
            Features.API_KEY,
            Features.SCANNING_PROFILES,
            Features.VULN_RETEST,
            Features.PAUSE_RESUME,
        }
        self.scan_apps = (ScanAppTypes.WVS, ScanAppTypes.OVAS)
        self.max_targets = 2
        self.max_network_targets = 2
        self.max_users = 1


class OnPremiseLicense(BaseLicense):
    def __init__(self, license_data):
        super().__init__(license_data)
        self.max_demo_targets = 5
        self.max_scans_per_engine = 20

    @property
    def max_scans_per_license(self):
        if self.max_engines is None:
            return 100
        else:
            return self.max_scans_per_engine * self.max_engines


class OnPremiseTrial(OnPremiseLicense):
    def __init__(self, license_data):
        super().__init__(license_data)
        self._features = {
            Features.COMPLIANCE_REPORTS,
            Features.CONTINUOUS_SCANS,
            Features.TARGET_GROUPS,
            Features.TARGET_BUSINESS_CRITICALITY,
            Features.TREND_GRAPHS,
            Features.EXPORT_WAF,
            Features.DELETE_TARGETS,
            Features.ENFORCE_ACUNETIX_HEADERS,
            Features.SCANNING_PROFILES,
            Features.BUG_TRACKING_INTEGRATION,
        }
        self.scan_apps = (ScanAppTypes.WVS,)
        self.max_targets = 5
        self.max_users = license_data.get("max_users", 2)
        self.max_engines = 1
        self.max_scans_per_engine = 5


class OnPremisePocV12(OnPremiseLicense):
    def __init__(self, license_data):
        super().__init__(license_data)
        self._features = {
            Features.COMPLIANCE_REPORTS,
            Features.CONTINUOUS_SCANS,
            Features.TARGET_GROUPS,
            Features.TARGET_BUSINESS_CRITICALITY,
            Features.TREND_GRAPHS,
            Features.EXPORT_WAF,
            Features.BUG_TRACKING_INTEGRATION,
            Features.OFFLINE_ACTIVATIONS,
            Features.VULN_RETEST,
            Features.ACUMONITOR,
            Features.DELETE_TARGETS,
            Features.ENFORCE_ACUNETIX_HEADERS,
            Features.ON_PREMISE_UPDATES,
            Features.SCANNING_PROFILES,
            Features.PAUSE_RESUME,
            Features.API_KEY,
        }
        self.scan_apps = (ScanAppTypes.WVS,)
        self.max_targets = license_data.get("max_targets", 25)
        self.max_users = license_data.get("max_users", 3)
        self.max_engines = license_data.get("max_engines", 1)


class OnPremiseStandardV12(OnPremiseLicense):
    def __init__(self, license_data):
        super().__init__(license_data)
        self._features = {
            Features.OFFLINE_ACTIVATIONS,
            Features.ENFORCE_ACUNETIX_HEADERS,
            Features.VULN_RETEST,
            Features.ACUMONITOR,
            Features.ON_PREMISE_UPDATES,
            Features.SCANNING_PROFILES,
            Features.PAUSE_RESUME,
        }
        if license_data["product_code"].endswith("UNL"):
            self._features.add(Features.DELETE_TARGETS)
        self.max_targets = license_data.get("max_targets", 0)
        self.scan_apps = (ScanAppTypes.WVS,)
        self.max_users = license_data.get("max_users", 1)
        self.max_engines = license_data.get("max_engines", 1)


class OnPremiseProV12(OnPremiseLicense):
    def __init__(self, license_data):
        super().__init__(license_data)
        self._features = {
            Features.COMPLIANCE_REPORTS,
            Features.OFFLINE_ACTIVATIONS,
            Features.VULN_RETEST,
            Features.ACUMONITOR,
            Features.DELETE_TARGETS,
            Features.ON_PREMISE_UPDATES,
            Features.SCANNING_PROFILES,
            Features.PAUSE_RESUME,
        }
        self.scan_apps = (ScanAppTypes.WVS,)
        self.max_targets = license_data.get("max_targets", 5)
        self.max_users = license_data.get("max_users", 1)
        self.max_engines = license_data.get("max_engines", 1)


class OnPremiseEnterpriseV12(OnPremiseLicense):
    def __init__(self, license_data):
        super().__init__(license_data)
        self._features = {
            Features.COMPLIANCE_REPORTS,
            Features.CONTINUOUS_SCANS,
            Features.TARGET_GROUPS,
            Features.TARGET_BUSINESS_CRITICALITY,
            Features.TREND_GRAPHS,
            Features.EXPORT_WAF,
            Features.BUG_TRACKING_INTEGRATION,
            Features.API_KEY,
            Features.OFFLINE_ACTIVATIONS,
            Features.VULN_RETEST,
            Features.ACUMONITOR,
            Features.ON_PREMISE_UPDATES,
            Features.SCANNING_PROFILES,
            Features.PAUSE_RESUME,
        }
        self.scan_apps = (ScanAppTypes.WVS,)
        self.max_engines = license_data.get("max_engines", 1)
        self.max_targets = license_data.get("max_targets", 0)
        self.max_users = license_data.get("max_users")


class OnPremiseServiceProviderV12(OnPremiseLicense):
    def __init__(self, license_data):
        super().__init__(license_data)
        self._features = {
            Features.COMPLIANCE_REPORTS,
            Features.CONTINUOUS_SCANS,
            Features.TARGET_GROUPS,
            Features.TARGET_BUSINESS_CRITICALITY,
            Features.TREND_GRAPHS,
            Features.EXPORT_WAF,
            Features.BUG_TRACKING_INTEGRATION,
            Features.API_KEY,
            Features.OFFLINE_ACTIVATIONS,
            Features.VULN_RETEST,
            Features.ACUMONITOR,
            Features.DELETE_TARGETS,
            Features.ON_PREMISE_UPDATES,
            Features.SCANNING_PROFILES,
            Features.PAUSE_RESUME,
        }
        self.scan_apps = (ScanAppTypes.WVS,)
        self.max_targets = license_data.get("max_targets", None)
        self.max_users = license_data.get("max_users")
        self.max_engines = license_data("max_engines", 1)


def is_report_id_waf_export_id(report_template_id):
    if not isinstance(report_template_id, UUID):
        report_template_id = UUID(report_template_id)
    return report_template_id in (
        UUID("21111111111111111111111111111112"),
        UUID("21111111111111111111111111111118"),
        UUID("21111111111111111111111111111119"),
        UUID("21111111111111111111111111111113"),
    )


def is_report_id_compliance_id(report_template_id):
    if not isinstance(report_template_id, UUID):
        report_template_id = UUID(report_template_id)
    return report_template_id in (
        UUID("11111111111111111111111111111121"),
        UUID("11111111111111111111111111111122"),
        UUID("11111111111111111111111111111120"),
        UUID("11111111111111111111111111111118"),
        UUID("11111111111111111111111111111123"),
        UUID("11111111111111111111111111111114"),
        UUID("11111111111111111111111111111116"),
        UUID("11111111111111111111111111111117"),
    )
